﻿// Extensions Made Easy - Copyright 2012 by Jan Van der Haegen - All rights reserved, use for educational purposes only.

using System;
using System.ComponentModel;
using System.Windows.Media;
using ExtensionsMadeEasy.ClientAPI.Commands;
using ExtensionsMadeEasy.ClientAPI.Utilities.Base;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Client;
using Microsoft.LightSwitch.Presentation.Framework.Converters.Internal;
using Microsoft.LightSwitch.Runtime.Shell.ViewModels.Commands;
using Microsoft.LightSwitch.Threading;
using System.Windows;
using System.Globalization;
using System.Diagnostics;

namespace ExtensionsMadeEasy.Presentation.Commands
{
    public sealed class EasyCommand : NotifyPropertyChangedBase, IShellCommand, IExecutable
    {
        public IEasyCommandExporter InnerCommand { get; private set; }

        private readonly string groupName;

        public IScreenObject CurrentScreen { get; set; }

        private Exception exception = null;

        public EasyCommand(IEasyCommandExporter innerCommand, string groupName)
        {
            this.InnerCommand = innerCommand;
            this.groupName = groupName;
            this.InnerCommand.PropertyChanged += new PropertyChangedEventHandler(innerCommand_PropertyChanged);
             

        }

        ~EasyCommand()
        {
            this.InnerCommand.PropertyChanged -= new PropertyChangedEventHandler(innerCommand_PropertyChanged);
            this.InnerCommand = null;
            this.CurrentScreen = null;
        }

        public string Description
        {
            get
            {
                return this.InnerCommand.Description;
            }
        }

        public string DisplayName
        {
            get
            {
                return this.InnerCommand.DisplayName;
            }
        }

        public string SortName 
        {
            get 
            {
                return String.Format("{0}-{1}",
                    this.InnerCommand.PrefixUsedForSortingWithinGroup,
                    this.InnerCommand.DisplayName);
            }
        }

        public Microsoft.LightSwitch.IExecutable ExecutableObject
        {
            get
            {
                return this;
            }
        }

        public string Group
        {
            get
            {
                return this.groupName;
            }
        }

        private ImageSource image;

        public ImageSource Image
        {
            get
            {
                if (this.image == null)
                {
                    this.image = new System.Windows.Media.Imaging.BitmapImage(this.InnerCommand.ImageUri);
                }

                return this.image;
            }
        }

        public bool IsEnabled
        {
            get
            {
                return this.InnerCommand.IsEnabled;
            }
        }

        public bool IsVisible
        {
            get
            {
                return true;
            }
        }

        public bool ShowSmallImage
        {
            get
            {
                return this.InnerCommand.UseSmallImage;
            }
        }

        void innerCommand_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.OnPropertyChanged(e.PropertyName);
        }
        

        public bool CanExecute
        {
            get
            {
                return true;
            }
        }

        public bool CanExecuteAsync
        {
            get
            {
                return true;
            }
        }

        public bool CanExecuteAsyncCancel
        {
            get
            {
                return false;
            }
        }

        public void Execute()
        {
            this.ExecuteAsync() ;
        }

        public void ExecuteAsync()
        {
            IDispatcher dispatcher = Microsoft.LightSwitch.Threading.Dispatchers.Main;

            if (this.CurrentScreen != null && !this.InnerCommand.ForceMainDispatcher)
            {
                dispatcher = this.CurrentScreen.Details.Dispatcher;
            }

            dispatcher.BeginInvoke(
                () =>
                {
                    this.exception = null;
                    try
                    {
                        this.InnerCommand.Execute(this.CurrentScreen);
                    }
                    catch (Exception x)
                    {
                        this.exception = x;
                    }
                    finally
                    {
                        if (this.ExecuteCompleted != null)
                        {
                            this.ExecuteCompleted(this, new ExecuteCompletedEventArgs(this.exception, false, null));
                        }
                    }
                });
        }

        public void ExecuteAsyncCancel()
        {
            return;
        }

        public event EventHandler<ExecuteCompletedEventArgs> ExecuteCompleted;

        public Exception ExecutionError
        {
            get
            {
                return this.exception;
            }
        }

        public ExecutionState ExecutionState
        {
            get
            {
                return this.exception == null ? ExecutionState.NotExecuted : ExecutionState.HasError;
            }
        }
    }
}